package cn.shop.admin.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.shop.admin.common.util.CurrentUserUtil;
import cn.shop.admin.entity.backUserModule.AdminMenuVO;
import cn.shop.admin.entity.backUserModule.BackUser;
import cn.shop.admin.entity.backUserModule.TransactionPasswordReq;
import cn.shop.admin.mapper.BackPermissionMapper;
import cn.shop.admin.mapper.BackUserMapper;
import cn.shop.admin.req.AssignRoleReq;
import cn.shop.admin.service.BackRoleService;
import cn.shop.admin.service.BackSettingService;
import cn.shop.admin.service.BackUserService;
import cn.shop.base.MyServiceImpl;
import cn.shop.transcation.backSetting.entity.BackSetting;
import cn.shop.utils.ApiCode;
import cn.shop.utils.constant.Constant;
import cn.shop.utils.constant.Regular;
import cn.shop.utils.constant.SMSVerificationCode;
import cn.shop.utils.constant.SystemSettingConstant;
import cn.shop.utils.exception.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 总后台角色表(BackUser)表服务实现类
 *
 * @author jzw
 * @since 2021-11-02 11:35:13
 */
@Service("backUserService")
public class BackUserServiceImpl extends MyServiceImpl<BackUserMapper, BackUser> implements BackUserService {

	@Resource
	private BackPermissionMapper backPermissionMapper;

	@Resource
	private BackRoleService roleService;

	@Resource
	private BackSettingService backSettingService;

	/**
	 * 设置交易密码
	 *
	 * @param transactionPasswordReq
	 * @return
	 * @author jzw
	 * @since 2022/2/23 14:59
	 */
	@Override
	public boolean setTransactionPassword(TransactionPasswordReq transactionPasswordReq) {

		SaSession session = SaSessionCustomUtil.getSessionById(SMSVerificationCode.TRANSACTION_PASSWORD_KEY + transactionPasswordReq.getPhone());
		if (session != null) {
			String code = (String) session.get("code");
			if (code != null && code.equalsIgnoreCase(transactionPasswordReq.getCode())) {
				session.logout();
				LambdaUpdateWrapper<BackSetting> lambdaUpdate = Wrappers.lambdaUpdate();
				lambdaUpdate.set(BackSetting::getValue, DigestUtil.bcrypt(transactionPasswordReq.getPassword())).eq(BackSetting::getKey, SystemSettingConstant.ADMIN_TRANSACTION_PASSWORD);
				// BackUser backUser = new BackUser();
				// backUser.setTransactionPassword(DigestUtil.bcrypt(transactionPasswordReq.getPassword()));
				// backUser.setId(CurrentUserUtil.getUserId());
				return backSettingService.update(lambdaUpdate);
			}
		}
		throw new ServiceException("验证码不正确");
	}

	/**
	 * 批量设置内置账户
	 *
	 * @param idList 账户id
	 * @author jy
	 * @since 2022/1/17 14:50
	 */
	@Override
	public boolean setInitAccount(List<Long> idList) {
		if (idList.size() > 0) {
			//去除所有内置账户
			LambdaUpdateWrapper<BackUser> updateWrapper = Wrappers.lambdaUpdate();
			updateWrapper.eq(BackUser::getInitial, true).set(BackUser::getInitial, false);
			BackUser entity = new BackUser();
			baseMapper.update(entity, updateWrapper);
			//重新分配内置账户
			LambdaUpdateWrapper<BackUser> updateInitWrapper = Wrappers.lambdaUpdate();
			updateInitWrapper.in(BackUser::getId, idList).set(BackUser::getInitial, true);
			return SqlHelper.retBool(baseMapper.update(entity, updateInitWrapper));
		}
		return false;
	}

	/**
	 * 启禁用账户
	 *
	 * @param accountId 账户id
	 * @author jy
	 * @since 2022/1/17 13:45
	 */
	@Override
	public boolean disOrEnaAccount(Long accountId) {
		BackUser user = new BackUser();
		LambdaUpdateWrapper<BackUser> updateWrapper = Wrappers.lambdaUpdate();
		updateWrapper.eq(BackUser::getInitial, false).setSql("enable = not enable").eq(BackUser::getId, accountId);
		return SqlHelper.retBool(baseMapper.update(user, updateWrapper));
	}

	/**
	 * 新增一条用户信息
	 *
	 * @param backUser
	 * @return void
	 * @author jzw
	 * @since 2021/11/2 16:52
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean insert(BackUser backUser) {

		LambdaQueryWrapper<BackUser> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(BackUser::getAccount, backUser.getAccount());
		BackUser exist = baseMapper.selectOne(queryWrapper);
		if (exist != null) {
			throw new ServiceException("当前账户已存在!");
		}
		backUser.setPassword(DigestUtil.bcrypt(backUser.getPassword()));
		backUser.setEnable(true);
		backUser.setInitial(false);
		int insert = baseMapper.insert(backUser);
		// 添加默认角色
		List<Object> roleIds = roleService.listDefaultRole();
		if (roleIds != null && roleIds.size() > 0) {
			roleService.assignRole(new AssignRoleReq(backUser.getId(), roleIds));
		}
		return SqlHelper.retBool(insert);

	}

	/**
	 * 修改一条用户信息
	 *
	 * @param backUser
	 * @return void
	 * @author jzw
	 * @since 2021/11/2 16:52
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean update(BackUser backUser) {
		backUser.setAccount(null);
		String password = backUser.getPassword();
		if (StrUtil.isNotBlank(password)) {
			boolean match = ReUtil.isMatch(Regular.PASSWORD, password);
			if (!match) {
				throw new ServiceException(Regular.PASSWORD_MASSAGE, ApiCode.PARAMETER_ERROR);
			}
			backUser.setPassword(DigestUtil.bcrypt(password));
		}
		return SqlHelper.retBool(baseMapper.updateById(backUser));
	}

	/**
	 * 获取验证码
	 *
	 * @param response
	 * @return
	 * @author jzw
	 * @since 2021/11/4 14:03
	 */
	@Override
	public void verificationCode(HttpServletResponse response) {
		//定义图形验证码的长、宽、验证码字符数、干扰元素个数
		LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 32, 4, 4);
		try (ServletOutputStream outputStream = response.getOutputStream()) {
			Cookie cookie = new Cookie("verificationCode", captcha.getCode());
			cookie.setPath("/");
			cookie.setMaxAge(1800);
			response.addCookie(cookie);
			SaSession tokenSession = StpUtil.getTokenSession();
			tokenSession.delete(Constant.CAPTCHA_SESSION_KEY);
			tokenSession.set(Constant.CAPTCHA_SESSION_KEY, captcha.getCode());
			//图形验证码写出，可以写出到文件，也可以写出到流
			captcha.write(outputStream);
			outputStream.flush();
		} catch (IOException e) {
			log.error(e.getMessage());
		}
	}

	/**
	 * 通过userId 获取权限code
	 *
	 * @param id 用户id
	 * @return 权限code
	 * @author jzw
	 * @since 2021/11/11 14:10
	 */
	@Override
	public List<String> roleCodeByUserId(Long id) {
		return baseMapper.selectRoleCodeByUserId(id);
	}


	/**
	 * 获取当前登录人菜单
	 *
	 * @author jy
	 * @since 2022/1/17 13:49
	 */
	@Override
	public List<AdminMenuVO> getMenuList() {
		List<AdminMenuVO> menuList = baseMapper.getMenuListByUserId(CurrentUserUtil.getUserId());
		if (menuList.size() == 0) {
			return Collections.emptyList();
		}
		Map<Long, List<AdminMenuVO>> collect = menuList.stream().collect(Collectors.groupingBy(AdminMenuVO::getParentId));
		List<AdminMenuVO> parent = collect.get(0L);
		parseList(parent, collect);
		return parent;
	}

	/**
	 * 递归拼接菜单
	 */
	private void parseList(List<AdminMenuVO> parent, Map<Long, List<AdminMenuVO>> permissions) {
		for (AdminMenuVO adminMenuVO : parent) {
			Long id = adminMenuVO.getPermissionId();
			List<AdminMenuVO> children = permissions.get(id);
			if (CollectionUtil.isNotEmpty(children)) {
				adminMenuVO.setSubMenu(children);
				parseList(children, permissions);
			}
		}
	}

}

